/*
 * COPYRIGHT. ShenZhen JiMi Technology Co., Ltd. 2017.
 * ALL RIGHTS RESERVED.
 *
 * No part of this publication may be reproduced, stored in a retrieval system, or transmitted,
 * on any form or by any means, electronic, mechanical, photocopying, recording, 
 * or otherwise, without the prior written permission of ShenZhen JiMi Network Technology Co., Ltd.
 *
 * Amendment History:
 * 
 * Date                   By              Description
 * -------------------    -----------     -------------------------------------------
 * 2017年4月10日    li.shangzhi         Create the class
 * http://www.jimilab.com/
 */

package com.jimi.framework.mybatis.config;

import java.sql.SQLException;

import javax.sql.DataSource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import com.alibaba.druid.pool.DruidDataSource;

/**
 * @FileName DataSourceConfiguration.java
 * @Description: 数据源配置/可以配置多个数据源
 *
 * @Date 2017年4月10日 上午9:54:42
 * @author li.shangzhi
 * @version 1.0
 */
@Configuration
@EnableTransactionManagement
public class DataSourceConfiguration implements EnvironmentAware {

	private Logger logger = LoggerFactory.getLogger(DataSourceConfiguration.class);

	private static String driverClassName = "driver-class-name";
	private static String url = "url";
	private static String username = "username";
	private static String password = "password";
	// 配置初始化大小、最小、最大
	private static String initialSize = "initialSize";
	private static String minIdle = "minIdle";
	private static String maxActive = "maxActive";
	// 配置获取连接等待超时的时间
	private static String maxWait = "maxActive";
	// 配置间隔多久才进行一次检测，检测需要关闭的空闲连接，单位是毫秒
	private static String timeBetweenEvictionRunsMillis = "timeBetweenEvictionRunsMillis";
	// 配置一个连接在池中最小生存的时间，单位是毫秒
	private static String minEvictableIdleTimeMillis = "minEvictableIdleTimeMillis";
	private static String validationQuery = "validationQuery";
	private static String testWhileIdle = "testWhileIdle";
	private static String testOnBorrow = "testOnBorrow";
	private static String testOnReturn = "testOnReturn";
	// 打开PSCache，并且指定每个连接上PSCache的大小
	private static String poolPreparedStatements = "poolPreparedStatements";
	private static String maxPoolPreparedStatementPerConnectionSize = "maxPoolPreparedStatementPerConnectionSize";
	// 配置监控统计拦截的filters，去掉后监控界面sql无法统计，'wall'用于防火墙
	private static String filters = "filters";
	// 通过connectProperties属性来打开mergeSql功能；慢SQL记录
	private static String connectionProperties = "connectionProperties";

	private RelaxedPropertyResolver masterResolver;

	private RelaxedPropertyResolver slaveResolver;

	@Override
	public void setEnvironment(Environment environment) {
		this.masterResolver = new RelaxedPropertyResolver(environment, "spring.datasource.");

		this.slaveResolver = new RelaxedPropertyResolver(environment, "tuqiang.datasource.");
	}

	@Bean(name = "masterDataSource", destroyMethod = "close", initMethod = "init")
	@Primary
	public DataSource masterDataSource() {
		logger.debug("Configruing Master DataSource by Druid");
		DruidDataSource datasource = new DruidDataSource();
		loadDataSource(datasource, masterResolver);
		return datasource;
	}

	@Bean(name = "slaveDataSource", destroyMethod = "close", initMethod = "init")
	public DataSource slaveDataSource() {
		logger.debug("Configruing Slave DataSource by Druid");
		DruidDataSource datasource = new DruidDataSource();
		loadDataSource(datasource, slaveResolver);
		return datasource;
	}

	private void loadDataSource(DruidDataSource datasource, RelaxedPropertyResolver resolver) {
		datasource.setDriverClassName(resolver.getProperty(driverClassName));
		datasource.setUrl(resolver.getProperty(url));
		datasource.setUsername(resolver.getProperty(username));
		datasource.setPassword(resolver.getProperty(password));
		datasource.setInitialSize(Integer.valueOf(resolver.getProperty(initialSize)));
		datasource.setMinIdle(Integer.valueOf(resolver.getProperty(minIdle)));
		datasource.setMaxWait(Long.valueOf(resolver.getProperty(maxWait)));
		datasource.setMaxActive(Integer.valueOf(resolver.getProperty(maxActive)));

		datasource.setTimeBetweenEvictionRunsMillis(Long.valueOf(resolver.getProperty(timeBetweenEvictionRunsMillis)));
		datasource.setMinEvictableIdleTimeMillis(Long.valueOf(resolver.getProperty(minEvictableIdleTimeMillis)));

		datasource.setValidationQuery(resolver.getProperty(validationQuery));
		datasource.setTestWhileIdle(Boolean.valueOf(resolver.getProperty(testWhileIdle)));
		datasource.setTestOnBorrow(Boolean.valueOf(resolver.getProperty(testOnBorrow)));
		datasource.setTestOnReturn(Boolean.valueOf(resolver.getProperty(testOnReturn)));

		datasource.setPoolPreparedStatements(Boolean.valueOf(resolver.getProperty(poolPreparedStatements)));
		datasource.setMaxPoolPreparedStatementPerConnectionSize(Integer.valueOf(resolver
				.getProperty(maxPoolPreparedStatementPerConnectionSize)));
		datasource.setConnectionProperties(resolver.getProperty(connectionProperties));
		try {
			datasource.setFilters(resolver.getProperty(filters));
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
}